/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package AccesoDatos.Datos;

import AccesoDatos.DTOs.Campo;
import AccesoDatos.DTOs.Registro;
import AccesoDatos.excepciones.ExcepcionDatos;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author gborrego
 */
class AdminDatos {        
    private Connection cn;
    private PreparedStatement ps;
    
    AdminDatos() {
        try {
            Class.forName("com.mysql.jdbc.Driver");            
            cn = DriverManager.getConnection(DatosConexion.getCadenaConexion(),
                    DatosConexion.USER,DatosConexion.PSW);
        } catch (SQLException e) {
            throw new RuntimeException("No se pudo cargar la base de datos con la cadena de conexion: "+
                    DatosConexion.getCadenaConexion());
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("No se pudo cargar el driver.");
        }
    } 
    
    private List<Registro> convierte(ResultSet rs) throws SQLException{
        List<Registro> consulta;
        consulta = new ArrayList<>();            
        ResultSetMetaData md = rs.getMetaData();               
        int numColumnas = md.getColumnCount();            
        Registro reg;            
        while (rs.next()) { 
            reg = new Registro();
            for (int i = 1; i <= numColumnas; i++) 
                reg.agregarValor(new Campo(md.getColumnLabel(i),rs.getObject(i)));
            consulta.add(reg);
        }            
        return consulta;        
    }
    
    private void insertarParametros(Object[] params) throws SQLException{
        if (params != null) 
            for (int i = 1; i <= params.length; i++) 
                ps.setObject(i, params[i - 1]);                    
    }
    
    void actualizar(String sql, Object[] params) throws ExcepcionDatos {
        try {
            ps = cn.prepareStatement(sql);
            insertarParametros(params);
            ps.executeUpdate();
        } catch (SQLException ex) {
            throw new ExcepcionDatos("No se pudo ejecutar la instrucción "+sql,ex);
        }
    }
    
    List<Registro> consultar(String sql, Object[] params) throws ExcepcionDatos {
        ResultSet rs = null; 
        try {
            ps = cn.prepareStatement(sql);
            insertarParametros(params);            
            rs = ps.executeQuery();
            return convierte(rs);
        } catch (SQLException ex) {
            throw new ExcepcionDatos("No se pudo realizar la consulta: " + sql, ex);
        } finally {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException ex) {}
            }
        }
    }   
    
    void insert (String tabla, String campos, Object[] params) throws ExcepcionDatos {
        StringBuilder sb = new StringBuilder("insert into ");
        sb.append(tabla);
        if(campos != null){
            sb.append(" (");
            sb.append(campos);
            sb.append(")");
        }
        sb.append(" values(");
        for (int i = 0; i < params.length; i++) 
            sb.append("?,");            
        sb.replace(sb.length()-1, sb.length(), ");");
        this.actualizar(sb.toString(), params); 
    }
    
    void update(String tabla, String set, String where, Object[] params) throws ExcepcionDatos{
        StringBuilder sb = new StringBuilder("update ");
        sb.append(tabla);
        sb.append(" set ");
        sb.append(set);
        sb.append(" where ");
        sb.append(where);
        sb.append(";");
        this.actualizar(sb.toString(), params); 
    }
    
    void delete(String tabla,String where,Object[] params) throws ExcepcionDatos{
        StringBuilder sb = new StringBuilder("delete from ");
        sb.append(tabla);
        sb.append(" where ");
        sb.append(where);
        sb.append(";");
        this.actualizar(sb.toString(), params);
    }
    
    List<Registro> consultar(String sql) throws ExcepcionDatos {
        ResultSet rs = null;                
        try {
            rs = cn.createStatement().executeQuery(sql);
            return convierte(rs);
        } catch (SQLException ex) {
            throw new ExcepcionDatos("No se pudo realizar la consulta: " + sql, ex);
        } finally {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException ex) {}
            }
        }
    }
    
}
